/******************************************
 * Nombre del archivo: Op_Listas.java
 * Universidad del Valle de Guatemala
 * Curso: Algoritmos y Estructura de Datos
 * Autores:
 *      * Martín Guzmán     08041
 *      * David Hsieh       08225
 *      * Eduardo Mejicano  08058
 *      * Kevin Sánchez     08302
 * Fecha: 21 de agosto de 2009
 * Descripción:
*******************************************/

import java.util.ArrayList;
import java.util.LinkedList;

public class Op_Listas {
    private static String[] Operadores_listas = {"CAR", "CDR","'","LIST"};

    /*****************************************
     * Método: car
     * Autor: David Hsieh
     * Uso: Ver primer elemento de la lista
     * Retorno: Primer elemento de la lista.
     *****************************************/
    public static String car(ArrayList<String> lista_lit){
        return lista_lit.get(0);
    }

    /*****************************************
     * Método: cdr
     * Autor: Martín Guzmán
     * Uso: La función cdr de Lisp
     * Retorno: Una lista con todos menos el
     *          primer elemento de la misma.
     *****************************************/
    public static String cdr(ArrayList<String> lista_lit) { //Debería devolver lista
        String lista="";
        try{
            for(int i=1;i<lista_lit.size();i++){
                //System.out.println("operar cdr: "+lista_lit.get(i));//debuguear
                lista += lista_lit.get(i) + " ";
            }
            lista="("+lista.substring(0,lista.length()-1)+")";
        }catch(Exception exp){System.out.println("Not valid expression after the CDR command");}
        return lista;
    }

    /*****************************************
     * Método: Operar
     * Autor: Martín Guzmán
     * Uso: Manda a llamar a la operación
     *      respectiva (ya sea cdr o car)
     * Retorno: Un sting con la lista.
     *****************************************/
    public static String Operar(String operador,At_Lista_Literal lista){
        //operar un CAR
        if(operador.compareToIgnoreCase("CAR")==0) {
            return car(lista.getList());
        }
        //operar una lista literal directa '(1 2 3)=(1 2 3)
        else if(operador.compareToIgnoreCase("'")==0) {
            return lista.Obtener_valor();
        }
        //operar un CDR
        else if(operador.compareToIgnoreCase("CDR")==0) {
            return cdr(lista.getList());
        }
        return null;//este nunca debería pasar
    }
    /*****************************************
     * Método: Operar_List
     * Autor: Martín Guzmán
     * Uso: Opera la instrucción list
     * Retorno: Un sting con la lista unida.
     *****************************************/
    public static String Operar_List(String operador,LinkedList<String> unir_en_lista){

        //operar un LIST

        if(operador.compareToIgnoreCase("LIST")==0) {

            At_Lista lista_atomos;
            At_Variable Atomo_variable;
            LinkedList<String> resultado = new LinkedList<String>();

            for(int i=0;i<unir_en_lista.size();i++){

                String a = unir_en_lista.get(i);

                //significa que hay que evaluar una lista
                if(unir_en_lista.get(i).startsWith("(")){
                    lista_atomos = new At_Lista(a.substring(2, a.length()-2));
                    if (lista_atomos.lista.size()!=0){
                        resultado.add(lista_atomos.Obtener_valor());//calcula el resultado de la operación
                    }
                    else{
                        resultado.clear();
                        break;
                    }
                }
                else
                {
                    Atomo_variable = new At_Variable(a);
                    resultado.add(Atomo_variable.Obtener_valor());
                }

            }

            if(resultado.isEmpty()){
                System.out.println("Sorry a problem has ocurred with the LIST command");
                return null;
            }
            String result = "(";
            for(int i=0;i<resultado.size()-1;i++){
                result+=resultado.get(i)+" ";
            }
            result=result+resultado.getLast()+")";
            //System.out.println("Resultado del LIST: ."+result+".");
            return result;
        }

        return null;//este nunca debería pasar
    }

    /*****************************************
     * Método: getOperadores
     * Autor: Martín Guzmán
     * Uso: para obtener los operadores de esta
     *      clase desde afuera de ella
     * Retorno: un arreglo con operadores como
     *          cdr, car, ', etc..
     *****************************************/
    public static String[] getOperadores() {
        return Operadores_listas;
    }

    /*****************************************
     * Método: Buscar
     * Autor: Martín Guzmán
     * Uso: para ver si se encuentra determinado
     *      operador en esta clase
     * Retorno: Booleano con la respuesta
     *****************************************/
    public static boolean Buscar(String operador) {
        boolean retorno=false;
        for(int i=0;i<Op_Listas.Operadores_listas.length;i++){
            if(Operadores_listas[i].compareToIgnoreCase(operador)==0){
                retorno=true;
            }
        }
        return retorno;
    }


}